/**
   simulator.h - Created by Timothy Morey on 9/2/2011.

   This file defines the Simulator object, which encapsulates all of the data
   and operations associated with a particle simulation.
*/

#ifndef __SIMULATOR_H
#define __SIMULATOR_H

#include <vector>

class DeviceController;
class Renderer;
class VisServer;

struct Parameters
{
  int N;
  float MinX, MaxX, MinY, MaxY;
  float dt;
};

class Simulator
{
public:

  static Simulator& Instance();
  static void DestroyInstance();

public:
  ~Simulator();

public:
  const Parameters& GetParameters() const { return _Parameters; }

  DoF* GetX() { return _HostX; }
  DoF* GetY() { return _HostY; }
  DoF* GetVX() { return _HostVX; }
  DoF* GetVY() { return _HostVY; }
  DoF* GetVM() { return _HostVM; }
  DoF* GetAX() { return _HostAX; }
  DoF* GetAY() { return _HostAY; }

  unsigned char* GetFrame() { return _HostFrame; }
  unsigned int GetFrameWidth() const { return _FrameWidth; }
  unsigned int GetFrameHeight() const { return _FrameHeight; }

  DoF GetX(int i) const;
  DoF GetY(int i) const;
  DoF GetVM(int i) const;

  void PrintStepRateReport() const;

public:
  bool UpdateParameters(const Parameters& parms);
  void SetStepSize(DoF dt);

  bool RandomizePositions(int start = -1, int stop = -1);
  void RandomizeVelocities(DoF magnitude = 1.0,
			   int start = -1, int stop = -1);

  void SetVisServer(VisServer* vis) { _Vis = vis; }
  void SetFrameSize(unsigned int width, unsigned int height);

public:
  void Start();
  void Stop();
  void Pause();
  void Resume();

  void PrintParticles();

  bool StopFlag() const { return _StopFlag; }
  bool PauseFlag() const { return _PauseFlag; }
  bool IsRunning() const { return _Devices.size() > 0; }

protected:

  std::vector<DeviceController*> _Devices;
  Renderer* _Renderer;

  DoF* _HostX;
  DoF* _HostY;
  DoF* _HostVX;
  DoF* _HostVY;
  DoF* _HostVM;
  DoF* _HostAX;
  DoF* _HostAY;
  unsigned char* _HostFrame;

  unsigned int _FrameWidth;
  unsigned int _FrameHeight;

  Parameters _Parameters;

  pthread_barrier_t _Barrier;

  bool _PauseFlag;
  bool _StopFlag;

  VisServer* _Vis;

protected:
  Simulator();

  static Simulator* _Instance;
};

#endif
